From c000b0a87a3002480c5588eb98db219be42054c8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C3=98yvind=20Kol=C3=A5s?= Date: Sat, 21 Nov 2009 16:47:24 +0000 Subject: [PATCH] Made BablFishPath thread safe. Refactored static variables away and added a lock to protect state keeping inside the individual BablFormat when permutating possible conversion paths. --- babl/babl-fish-path.c | 101 +++++++++++++++++++++++++----------------- babl/babl-internal.c | 3 ++ babl/babl-internal.h | 1 + 3 files changed, 64 insertions(+), 41 deletions(-) diff --git a/babl/babl-fish-path.c b/babl/babl-fish-path.c index c7f28c2..756e673 100644 --- a/babl/babl-fish-path.c +++ b/babl/babl-fish-path.c @@ -26,21 +26,27 @@ #define BABL_MAX_NAME_LEN 1024 -typedef struct _FishPathInstrumentation { - Babl *fmt_rgba_double; - double *test; - void *source; - void *destination; - void *ref_destination; - double *destination_rgba_double; - double *ref_destination_rgba_double; - Babl *fish_rgba_to_source; - Babl *fish_reference; - Babl *fish_destination_to_rgba; - double reference_cost; - int init_instrumentation_done; +typedef struct _FishPathInstrumentation +{ + Babl *fmt_rgba_double; + double *test; + void *source; + void *destination; + void *ref_destination; + double *destination_rgba_double; + double *ref_destination_rgba_double; + Babl *fish_rgba_to_source; + Babl *fish_reference; + Babl *fish_destination_to_rgba; + double reference_cost; + int init_instrumentation_done; } FishPathInstrumentation; +typedef struct PathContext { + Babl *fish_path; + Babl *to_format; + BablList *current_path; +} PathContext; static void init_path_instrumentation (FishPathInstrumentation *fpi, @@ -64,7 +70,8 @@ process_conversion_path (BablList *path, long n); static void -get_conversion_path (Babl *current_format, +get_conversion_path (PathContext *pc, + Babl *current_format, int current_length, int max_length); @@ -132,14 +139,12 @@ static int max_path_length (void) * implemented by recursive function get_conversion_path (). */ -static Babl *fish_path; -static Babl *to_format; -static BablList *current_path; static void -get_conversion_path (Babl *current_format, - int current_length, - int max_length) +get_conversion_path (PathContext *pc, + Babl *current_format, + int current_length, + int max_length) { if (current_length > max_length) { @@ -147,7 +152,7 @@ get_conversion_path (Babl *current_format, * depth, let's bail out */ return; } - else if ((current_length > 0) && (current_format == to_format)) + else if ((current_length > 0) && (current_format == pc->to_format)) { /* We have found a candidate path, let's * see about it's properties */ @@ -156,9 +161,9 @@ get_conversion_path (Babl *current_format, double path_error = 1.0; int i; - for (i = 0; i < babl_list_size (current_path); i++) + for (i = 0; i < babl_list_size (pc->current_path); i++) { - path_error *= (1.0 + babl_conversion_error ((BablConversion *) current_path->items[i])); + path_error *= (1.0 + babl_conversion_error ((BablConversion *) pc->current_path->items[i])); } if (path_error - 1.0 <= legal_error ()) /* check this before the next; @@ -167,18 +172,18 @@ get_conversion_path (Babl *current_format, { FishPathInstrumentation fpi; memset (&fpi, 0, sizeof (fpi)); - get_path_instrumentation (&fpi, current_path, &path_cost, &ref_cost, &path_error); + get_path_instrumentation (&fpi, pc->current_path, &path_cost, &ref_cost, &path_error); if ((path_cost < ref_cost) && /* do not use paths that took longer to compute than reference */ - (path_cost < fish_path->fish_path.cost) && + (path_cost < pc->fish_path->fish_path.cost) && (path_error <= legal_error ())) { /* We have found the best path so far, * let's copy it into our new fish */ - fish_path->fish_path.cost = path_cost; - fish_path->fish.error = path_error; - babl_list_copy (current_path, - fish_path->fish_path.conversion_list); + pc->fish_path->fish_path.cost = path_cost; + pc->fish_path->fish.error = path_error; + babl_list_copy (pc->current_path, + pc->fish_path->fish_path.conversion_list); } destroy_path_instrumentation (&fpi); @@ -187,10 +192,12 @@ get_conversion_path (Babl *current_format, else { /* - * Bummer, we have to search deeper... */ + * Bummer, we have to search deeper... + */ BablList *list; int i; + list = current_format->format.from_list; if (list) { @@ -205,16 +212,16 @@ get_conversion_path (Babl *current_format, if (!next_format->format.visited) { /* next_format is not in the current path, we can pay a visit */ - babl_list_insert_last (current_path, next_conversion); - get_conversion_path (next_format, current_length + 1, max_length); - babl_list_remove_last (current_path); + babl_list_insert_last (pc->current_path, next_conversion); + get_conversion_path (pc, next_format, current_length + 1, max_length); + babl_list_remove_last (pc->current_path); } } /* Remove the current format from current path */ current_format->format.visited = 0; } - } + } } static char * @@ -263,13 +270,23 @@ babl_fish_path (const Babl *source, babl->fish_path.loss = BABL_MAX_COST_VALUE; babl->fish_path.conversion_list = babl_list_init_with_size (BABL_HARD_MAX_PATH_LENGTH); - current_path = babl_list_init_with_size (BABL_HARD_MAX_PATH_LENGTH); - fish_path = babl; - to_format = (Babl *) destination; - - get_conversion_path ((Babl *) source, 0, max_path_length ()); - - babl_list_destroy (current_path); + { + PathContext pc; + pc.current_path = babl_list_init_with_size (BABL_HARD_MAX_PATH_LENGTH); + pc.fish_path = babl; + pc.to_format = (Babl *) destination; + + babl_mutex_lock (babl_format_mutex); + /* we hold a global lock whilerunning get_conversion_path since + * it depends on keeping the various format.visited members in + * a consistent state, this code path is not performance critical + * since created fishes are cached. + */ + + get_conversion_path (&pc, (Babl *) source, 0, max_path_length ()); + babl_mutex_unlock (babl_format_mutex); + babl_list_destroy (pc.current_path); + } if (babl_list_size (babl->fish_path.conversion_list) == 0) { @@ -506,6 +523,7 @@ get_path_instrumentation (FishPathInstrumentation *fpi, fpi->ref_destination_rgba_double, NUM_TEST_PIXELS * 4); +#if 0 fpi->fish_rgba_to_source->fish.processings--; fpi->fish_reference->fish.processings--; fpi->fish_destination_to_rgba->fish.processings -= 2; @@ -513,6 +531,7 @@ get_path_instrumentation (FishPathInstrumentation *fpi, fpi->fish_rgba_to_source->fish.pixels -= NUM_TEST_PIXELS; fpi->fish_reference->fish.pixels -= NUM_TEST_PIXELS; fpi->fish_destination_to_rgba->fish.pixels -= 2 * NUM_TEST_PIXELS; +#endif *ref_cost = fpi->reference_cost; } diff --git a/babl/babl-internal.c b/babl/babl-internal.c index f8689ce..7155bcf 100644 --- a/babl/babl-internal.c +++ b/babl/babl-internal.c @@ -121,6 +121,7 @@ babl_process (Babl *babl, return -1; } +BablMutex *babl_format_mutex; #if BABL_DEBUG_MEM BablMutex *babl_debug_mutex; #endif @@ -130,6 +131,7 @@ babl_internal_init (void) { babl_set_malloc (malloc); babl_set_free (free); + babl_format_mutex = babl_mutex_new (); #if BABL_DEBUG_MEM babl_debug_mutex = babl_mutex_new (); #endif @@ -138,6 +140,7 @@ babl_internal_init (void) void babl_internal_destroy (void) { + babl_mutex_destroy (babl_format_mutex); #if BABL_DEBUG_MEM babl_mutex_destroy (babl_debug_mutex); #endif diff --git a/babl/babl-internal.h b/babl/babl-internal.h index 7606cac..451c5f8 100644 --- a/babl/babl-internal.h +++ b/babl/babl-internal.h @@ -239,6 +239,7 @@ babl_fatal (const char *format, ...) ) extern int babl_hmpf_on_name_lookups; +extern BablMutex *babl_format_mutex; #define BABL_DEBUG_MEM 1 #if BABL_DEBUG_MEM -- 2.30.2